package com.jdk21.demo.test.util;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class PasswordEncryptor {

    // 与前端一致的公钥
    private static final String PUBLIC_KEY = """
            -----BEGIN PUBLIC KEY-----
            MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0zI8aibR9ZN57QObFxvI
            wiRTmELItVVBLMrLd71ZqakR6oWUKkcAGgmxad2TCy3UeRe4A0Dduw97oXlbl5rK
            RGISzpLO8iMSYtsim5aXZX9SB5x3S9ees4CZ6MYD/4XQOTrU0r1TMT6wXlhVvwNb
            fMNYHm3vkY0rhfxBCVPFJoHjAGDFWNCAhf4KfalfvWsGL32p8N/exG2S4yXVHuV6
            cHDyFJAItKVmyuTmB62pnPs5KvNv6oPmtmhMxxsvBOyh7uLwB5TonxtZpWZ3A1wf
            43ByuU7F3qGnFqL0GeG/JuK+ZR40LARyevHy9OZ5pMa0Nwqb8PwfK810Bc8PxD8N
            EwIDAQAB
            -----END PUBLIC KEY-----""";

    // 密码字符集（与前端一致）
    private static final String ENCRYPT_PASS_CHARS =
            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz*&-%/!?*+=()";

    public static void main(String[] args) throws Exception {
        // 加密逻辑
        String encrypted = keyEncrypt("zj1234");
        System.out.println(encrypted);
    }

    // 核心加密方法（对应前端的 keyEncrypt）
    public static String keyEncrypt(String data) throws Exception {
        // 1. 生成随机密码（AES密钥）
        String passPhrase = generateEncryptPassword(32);

        // 2. 生成随机IV和Salt（与CryptoJS兼容）
        SecureRandom secureRandom = SecureRandom.getInstanceStrong();
        byte[] ivBytes = new byte[16]; // 128-bit IV
        byte[] saltBytes = new byte[16]; // 128-bit Salt
        secureRandom.nextBytes(ivBytes);
        secureRandom.nextBytes(saltBytes);
        String iv = bytesToHex(ivBytes);
        String salt = bytesToHex(saltBytes);

        // 3. 通过PBKDF2派生AES密钥（与CryptoJS配置一致）
        SecretKey aesKey = deriveAesKey(passPhrase, salt);

        // 4. AES加密数据
        String encryptedMessage = encryptWithAes(data, aesKey, iv);

        // 5. 拼接AES密钥信息并用RSA加密
        String aesKeyInfo = passPhrase + ":::" + salt + ":::" + iv;
        String encryptedKey = encryptWithRsa(aesKeyInfo);

        // 6. 返回最终结果（格式与前端一致）
        return encryptedKey + ":::" + encryptedMessage;
    }

    // 生成随机密码（对应前端的 generateEncryptPassword）
    private static String generateEncryptPassword(int length) {
        StringBuilder sb = new StringBuilder();
        SecureRandom random = new SecureRandom();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(ENCRYPT_PASS_CHARS.length());
            sb.append(ENCRYPT_PASS_CHARS.charAt(index));
        }
        return sb.toString();
    }

    // PBKDF2密钥派生（对应CryptoJS.PBKDF2）
    private static SecretKey deriveAesKey(String passPhrase, String salt)
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        PBEKeySpec spec = new PBEKeySpec(
                passPhrase.toCharArray(),
                hexToBytes(salt),
                1000, // iterations（与前端一致）
                128   // keySize（与前端一致）
        );
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        byte[] keyBytes = factory.generateSecret(spec).getEncoded();
        return new SecretKeySpec(keyBytes, "AES");
    }

    // AES加密（对应CryptoJS.AES.encrypt）
    private static String encryptWithAes(String data, SecretKey key, String iv)
            throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes(iv));
        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    // RSA加密（对应JSEncrypt）
    private static String encryptWithRsa(String data) throws Exception {
        // 移除PEM格式的头部/尾部
        String publicKeyPEM = PUBLIC_KEY
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s", "");

        // 解析公钥
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyPEM);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = factory.generatePublic(spec);

        // 加密数据
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    // 辅助方法：字节数组转Hex（兼容CryptoJS的Hex.parse）
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    // 辅助方法：Hex字符串转字节数组
    private static byte[] hexToBytes(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4
                    + Character.digit(hex.charAt(i + 1), 16)));
        }
        return data;
    }
}